/*
 * Copyright © 2017 eqxiu.com 北京中网易企秀科技有限公司  All rights reserved.
 */

package cn.hermit.nio.http.server;

import cn.hermit.util.StringUtils;
import cn.hermit.nio.http.Http;

import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;

/**
 * @author JackGao 高建国
 * @description //TODO 设计说明
 * @date 30/5/2017
 */
public class SimpleHttpRouter implements HttpRouter {

    private ConcurrentMap<String, HttpHandler> handlerCache = new ConcurrentHashMap<>();

    @Override
    public HttpHandler route(HttpRequest request) {
        String requestURI = request.getRequestURI();
        Http.Verb verb = request.getVerb();
        HttpHandler handler = (handlerCache.get(verb.name() + '@' + requestURI));
        if(handler != null) {
            return handler;
        }
        handler = handlerCache.get(requestURI);
        if(handler != null) {
            return handler;
        }
        String matchedKey = null;
        for(String routingKey : handlerCache.keySet()) {
            if(matchedKey != null && matchedKey.indexOf('@') != -1) {
                break;
            }
            int index = routingKey.indexOf('@');
            if(index == -1) {
                if(requestURI.matches(routingKey)) {
                    matchedKey = routingKey;
                }
            } else {
                String method = routingKey.substring(0, index);
                String path = routingKey.substring(index + 1);
                if(!method.equals(verb.name())) {
                    continue;
                }
                if(!requestURI.matches(path)) {
                    continue;
                }
                matchedKey = routingKey;
            }
        }
        if(matchedKey != null) {
            return handlerCache.get(matchedKey);
        }
        return null;
    }

    public void bind(String method, String path, HttpHandler handler) {
        String routingKey = path;
        if(!StringUtils.isBlank(method)) {
            routingKey = method.toUpperCase() + '@' + routingKey;
        }
        if(handlerCache.containsKey(routingKey)) {
            return;
        }
        handlerCache.putIfAbsent(routingKey, handler);
    }
}
